a tool for shared writing and social publishing
1import { z } from "zod";
2import type { Fact } from "src/replicache";
3import type { Attribute } from "src/replicache/attributes";
4import { makeRoute } from "../lib";
5import type { Env } from "./route";
6import { scanIndexLocal } from "src/replicache/utils";
7import { getBlocksWithTypeLocal } from "src/hooks/queries/useBlocks";
8import * as base64 from "base64-js";
9import { YJSFragmentToString } from "components/Blocks/TextBlock/RenderYJSFragment";
10import { applyUpdate, Doc } from "yjs";
11
12export const getFactsFromHomeLeaflets = makeRoute({
13 route: "getFactsFromHomeLeaflets",
14 input: z.object({
15 tokens: z.array(z.string()),
16 }),
17 handler: async ({ tokens }, { supabase }: Pick<Env, "supabase">) => {
18 let all_facts = await supabase.rpc("get_facts_for_roots", {
19 max_depth: 3,
20 roots: tokens,
21 });
22
23 if (all_facts.data) {
24 let titles = {} as { [key: string]: string };
25
26 let facts = all_facts.data.reduce(
27 (acc, fact) => {
28 if (!acc[fact.root_id]) acc[fact.root_id] = [];
29 acc[fact.root_id].push(fact as unknown as Fact<Attribute>);
30 return acc;
31 },
32 {} as { [key: string]: Fact<Attribute>[] },
33 );
34 for (let token of tokens) {
35 let scan = scanIndexLocal(facts[token]);
36 let [root] = scan.eav(token, "root/page");
37 let rootEntity = root?.data.value || token;
38 let [title] = getBlocksWithTypeLocal(facts[token], rootEntity).filter(
39 (b) => b.type === "text" || b.type === "heading",
40 );
41 if (!title) titles[token] = "Untitled";
42 else {
43 let [content] = scan.eav(title.value, "block/text");
44 if (!content) titles[token] = "Untitled";
45 else {
46 let doc = new Doc();
47 const update = base64.toByteArray(content.data.value);
48 applyUpdate(doc, update);
49 let nodes = doc.getXmlElement("prosemirror").toArray();
50 let stringValue = YJSFragmentToString(nodes[0]);
51 titles[token] = stringValue;
52 }
53 }
54 }
55 return {
56 result: { facts, titles },
57 };
58 }
59
60 return { result: {} };
61 },
62});